(function () {
    var calendar = {
        curDate: new Date(), //当前的日期对象
        holidays: ['假期安排', '元旦', '除夕', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节'],

        init() {
            this.renderSelect(this.curDate);  //渲染下拉列表
            this.getData(this.curDate);
        },

        renderSelect(d) { //渲染下拉列表
            var yearList = document.querySelector('.yearSelect .selectBox ul');
            var monthList = document.querySelector('.monthSelect .selectBox ul');
            var holidayList = document.querySelector('.holidaySelect .selectBox ul');

            var yearSelected = document.querySelector('.yearSelect .selected span');
            var monthSelected = document.querySelector('.monthSelect .selected span');
            var holidaySelected = document.querySelector('.holidaySelect .selected span');

            //生成年份
            var li = '';
            yearList.innerHTML = '';
            for (var i = 2010; i <= 2030; i++) {
                li += `<li ${i == d.getFullYear() ? 'class="active"' : ''}>${i}年</li>`
            }
            yearList.innerHTML = li;
            yearSelected.innerHTML = d.getFullYear() + '年';

            //生成月份
            var li = '';
            monthList.innerHTML = '';
            for (var i = 1; i <= 12; i++) {
                li += `<li ${i == (d.getMonth() + 1) ? 'class="active"' : ''}>${i}月</li>`
            }
            monthList.innerHTML = li;
            monthSelected.innerHTML = (d.getMonth() + 1) + '月';

            //生成假期
            var li = '';
            holidayList.innerHTML = '';
            for (var i = 0; i < this.holidays.length; i++) {
                li += `<li ${i == 0 ? 'class="active"' : ''}>${this.holidays[i]}</li>`
            }
            holidayList.innerHTML = li;
            holidaySelected.innerHTML = this.holidays[0];

            this.selectBindEvent();
            this.closeSelect();
        },

        closeSelect() { //关闭下拉框
            var selects = [...document.querySelectorAll('.select')];//所有的下拉框
            //原本是一个类数组，无法使用find方法。[...  ]转成真正的数组，es6提供(扩展运算符)
            var open = selects.find(select => select.classList.contains('active')); //有active的元素
            open && open.classList.remove("active");//只有找到有active的元素后才删除这个class
        },

        selectBindEvent() {  //给日期下拉框添加事件
            var selects = document.querySelectorAll('.select');//所有的下拉框

            selects.forEach((select, index) => {
                var cl = select.classList; // 元素身上的class集合
                var selected = select.querySelector('span');//当前点击的下拉框的选中内容

                select.onclick = ev => {
                    if (cl.contains('active')) { //点击的是自己就看自己身上有没有active
                        cl.remove('active');
                    } else {    //点击的是别人
                        this.closeSelect();//关掉别人的active
                        cl.add('active');//添加自己的active

                        this.scrollBar();//添加滚动条,在元素显示的时候添加
                    }

                    // console.log(ev.target); //事件源

                    if (ev.target.tagName != 'LI') { //成立，表示点击的不是列表
                        return;
                    }
                    var LIS = [...select.querySelectorAll('ul li')];
                    LIS.find(li => li.classList.contains('active')).classList.remove('active'); //把找到的active删除 
                    ev.target.classList.add('active');//给所点击的元素添加active

                    //根据索引值区分点击的是谁
                    switch (index) {
                        case 0: //点击的是年
                            this.curDate.setFullYear(parseInt(ev.target.innerHTML));//去中文
                            selected.innerHTML = ev.target.innerHTML;
                            break;
                        case 1: //点击的是月
                            this.curDate.setMonth(parseInt(ev.target.innerHTML) - 1);//月份从零开始
                            selected.innerHTML = ev.target.innerHTML;
                            break;
                        case 2: //点击的是假期
                            selected.innerHTML = ev.target.innerHTML;
                            break;
                    }

                    // console.log(this.curDate);

                    this.getData(this.curDate);//请求数据
                };//事件代理？啥玩意儿不懂
            });

            this.monthChange();//添加切换月份功能
            this.backToday();//添加返回今天功能
        },

        scrollBar() { //滑块
            var scrollWrap = document.querySelector('.yearSelect .selectBox');
            var content = document.querySelector('.yearSelect .selectBox ul');
            var barWrap = document.querySelector('.yearSelect .selectBox .scroll');
            var bar = document.querySelector('.yearSelect .selectBox span');

            //初始化
            bar.style.transfrom = content.style.transfrom = 'translateY(0)';

            //设置滑块的高度
            var multiple = (content.offsetHeight + 18) / scrollWrap.offsetHeight; //内容是内容父级的几倍
            multiple = multiple > 20 ? 20 : multiple; //设置倍数不能超过20，避免滑块过小
            bar.style.height = scrollWrap.offsetHeight / multiple + 'px'; //根据倍数算出滑块的高度

            // 滑块拖拽
            var scrollTop = 0;  //滑块走动距离
            var maxHeight = barWrap.offsetHeight - bar.offsetHeight; //滑块能走的最大距离

            bar.onmousedown = function (ev) {
                var startY = ev.clientY;
                var startT = parseInt(this.style.transfrom.split('(')[1]);  //['transLateY','0)'] 摁下时元素走的距离

                bar.style.transition = content.style.transition = null;

                document.onmousemove = ev => {
                    scrollTop = ev.clientY - startY + startT; // 滑块走动的距离

                    // console.log(scrollTop);
                    scroll(); //走的功能
                }

                document.onmouseup = () => document.onmousemove = null;
            };

            barWrap.onclick = ev => ev.stopPropagation();   // 在滑块的父级区间内摁下鼠标要阻止事件冒泡 

            function scroll() {
                if (scrollTop < 0) {
                    scrollTop = 0;
                } //上顶点

                if (scrollTop > maxHeight) {
                    scrollTop = maxHeight;
                } //下顶点

                var scaleY = scrollTop / maxHeight; //滑块走动的比例

                bar.style.transform = 'translateY(' + scrollTop + 'px)';
                content.style.transform = 'translateY(' + (scrollWrap.offsetHeight - content.offsetHeight - 18) * scaleY + 'px)';
            }

            scrollWrap.onwheel = ev => {    //滚轮事件
                ev.deltaY > 0 ? scrollTop += 10 : scrollTop -= 10; // ev.deltaY > 0 表示向下滚动
                bar.style.transition = content.style.transition = '.2s';
                scroll();

                ev.preventDefault(); //阻止浏览器默认滚轮行为
            }

        },

        getData(d) {//请求数据
            $.ajax({
                url: `https://www.rili.com.cn/rili/json/pc_wnl/${d.getFullYear()}/${d.getMonth() + 1}.js`,
                dataType: "jsonp",
            });

            window.jsonrun_PcWnl = res => { // 一定要把jsonp里的函数定义成全局的
                // console.log(res);
                this.rendarDate(d, res.data);    //渲染日期

                //渲染农历
                this.renderLunar(res.data.find(item => item.nian == d.getFullYear() && item.yue ==d.getMonth() + 1 && item.ri == d.getDate()));
            }
        },

        getEndDay: (year, month) => new Date(year, month, 0).getDate(), //获取到某个月的最后一天的日期
        /* 
            是几月就传几；
            month的索引从0开始，当参数month为10时，实际上是11月。
            11月的第0天就是10月的最后一天，若参数day为-1，则为10月的倒数第二天 
        */

        getFistWeek: (year, month) => new Date(year, month - 1, 1).getDay(),   //获取某个月的第一天是周几
        /*
            day参数为1，month不回滚，所以需要自己设置 -1 回滚
        */

        delTag: str => str.replace(/<\/?.+?\/?>/g, ''), //删除标签
        repair: v => v < 10 ? '0' + v : v, //补0

        rendarDate(d, data) { //渲染日期
            var tbody = document.querySelector('.dateWrap tbody');

            var lastEndDay = this.getEndDay(d.getFullYear(), d.getMonth());     //上个月的最后一天，月份不需要计算
            var curEndDay = this.getEndDay(d.getFullYear(), d.getMonth() + 1);  //当前月最后一天，月份要 +1 
            var week = this.getFistWeek(d.getFullYear(), d.getMonth() + 1);     //当前月的第一天是周几
            // console.log(lastEndDay,curEndDay,week);
            // console.log(data);

            var lastDateNum = week - 1; // 上个月占几个格子
            lastDateNum = week == 0 ? 6 : lastDateNum; // 当前月的第一天是周日，week的值为0，需要手动留出上个月的格子 6 个
            var prevStartDate = lastEndDay - lastDateNum + 1; //上个月的起始日期
            var nextStartDate = 1;
            var curStartDate = 1;

            var calendar = document.querySelector('#calendar');
            calendar.classList.remove('active');    //如果之前已经添加了，要先取消


            var cn = -1 //记录42次循环走的每一次
            tbody.innerHTML = '';
            for (var i = 0; i < 6; i++) {    //设置tr
                var tr = document.createElement('tr');
                var td = '';

                for (var j = 0; j < 7; j++) {//设置td
                    // td += '<td></td>';
                    cn++;

                    var festival = data[cn].jie ? this.delTag(data[cn].jie) : data[cn].r2;//看是否有节日，有节日就显示节日
                    //接口中的数据节日有<a>标签，需要删除
                    var weekday = data[cn].jia == 90 ? 'weekday' : '';
                    var holiday = data[cn].jia > 90 ? 'holiday' : '';
                    // 班 与 休； 90是接口的设定数字
                    if (cn < lastDateNum) { //上个月
                        td += `<td>
                                    <div class="prevMonth ${weekday + ' ' + holiday}">
                                        <span>${prevStartDate++}</span>
                                        <span>${festival}</span>
                                    </div>
                                </td>`;
                    } else if (cn >= lastDateNum + curEndDay) { //下个月
                        td += `<td>
                                    <div class="nextMonth  ${weekday + ' ' + holiday}">
                                        <span>${nextStartDate++}</span>
                                        <span>${festival}</span>
                                    </div>
                                </td>`;
                    } else { //当前月
                        var cl = '';
                        if (curStartDate == d.getDate()) { //格子里的日期与当前日期对象（this.curDate）里的日期做对比
                            cl = 'active';
                        }

                        // 这个条件成立时，循环的格子是今天的日期
                        if (
                            new Date().getFullYear() == d.getFullYear() &&
                            new Date().getMonth() == d.getMonth() &&
                            new Date().getDate() == d.getDate() &&
                            d.getDate() == curStartDate
                        ) {
                            cl += " today";
                        }
                        td += `<td>
                                    <div class="${cl + ' ' + weekday + ' ' + holiday}">
                                        <span>${curStartDate++}</span>
                                        <span>${festival}</span>
                                    </div>
                                </td>`;

                        if (cl.indexOf('active') != -1 && holiday == 'holiday') {
                            //这个条件满足表示是节假日，最外层的父级需要添加红色class
                            var curDay = this.delTag(data[cn].jie);//循环到dd是否是节日
                            this.holidays.includes(curDay) && calendar.classList.add("active");

                            /* 
                                添加红色active的条件
                                    当前的格子必须有active的class，表示激活状态
                                    当前的格子必须有holiday的class，表示当前是个节日
                                    节日必须为this.holiday的某一个
                            */
                        }
                    }
                    tr.innerHTML = td;
                }
                tbody.appendChild(tr);
            }

            this.dateBindEvent(data);
        },

        monthChange() { //切换月份
            var arrows = document.querySelectorAll('.arrow');
            //上个月
            arrows[0].onclick = () => {
                this.curDate.setMonth(this.curDate.getMonth() - 1);//月份 -1
                this.renderSelect(this.curDate); //渲染下拉框
                this.getData(this.curDate);//更新日期
                this.closeSelect();//取消下拉框
            }
            //下个月
            arrows[1].onclick = () => {
                this.curDate.setMonth(this.curDate.getMonth() + 1);
                this.renderSelect(this.curDate);//渲染下拉框
                this.getData(this.curDate);//更新日期
                this.closeSelect();//取消下拉框
            }
        },

        backToday() {   //返回今天
            var returnBtn = document.querySelector('#calendar .topBar button');

            returnBtn.onclick = () => {
                this.curDate = new Date();
                this.renderSelect(this.curDate); //渲染下拉框
                this.getData(this.curDate); //更新日期
            }
        },

        dateBindEvent(data) { //日期点击功能
            var boxes = [...document.querySelectorAll('.dateWrap tbody td div')];
            var last = boxes.find((box) => box.classList.contains('active'));

            var curYear = this.curDate.getFullYear(); //当前年
            var curMonth = this.curDate.getMonth(); //当前月

            boxes.forEach(
                (box, index) =>
                    box.onclick = () => {
                        //选项卡
                        var date = box.children[0].innerHTML; //点击的日期

                        var cl = box.classList;

                        last && last.classList.remove('active');
                        cl.add("active");
                        last = box;

                        this.closeSelect();//如果下拉框显示，点击的话需要隐藏

                        if (cl.contains('prevMonth')) { //上个月
                            this.curDate = new Date(curYear, curMonth - 1, date); //同时设置年月日
                            this.renderSelect(this.curDate);
                            this.getData(this.curDate);
                        } else if (cl.contains('nextMonth')) { //下个月
                            this.curDate = new Date(curYear, curMonth + 1, date);
                            this.renderSelect(this.curDate);
                            this.getData(this.curDate);
                        } else { //当前月
                            var calendar = document.querySelector('#calendar');
                            var curDay = box.children[1].innerHTML;
                            calendar.className = this.holidays.includes(curDay) ? 'active' : '';
                            this.renderLunar(data[index]); //渲染农历
                        }
                    },
            );
        },

        renderLunar(data) { //渲染农历
            var date = document.querySelector('.right .date');
            var day = document.querySelector('.right .day');
            var ps = document.querySelectorAll('.right .lunar p');
            var holidayList = document.querySelector('.right .holidayList');

            date.innerHTML = data.nian + '-' + this.repair(data.yue) + "-" + this.repair(data.ri);
            day.innerHTML = data.ri;
            ps[0].innerHTML = data.n_yueri;
            ps[1].innerHTML = data.gz_nian + '年 ' + data.shengxiao;
            ps[2].innerHTML = data.gz_yue + '月 ' + data.gz_ri;

            //节日
            var holidays = this.delTag(data.jieri).split(',');
            holidays = holidays.length > 2 ? holidays.slice(0, 2) : holidays;
            holidayList.innerHTML = '';
            holidays.forEach(holiday => holidayList.innerHTML += `<li>${holiday}</li>`);

            //宜，忌
            var defaultDl = document.querySelectorAll('.suit .default dl');

            defaultDl[0].innerHTML = '<dt>宜</dt>';
            data.yi.forEach(yi => defaultDl[0].innerHTML += `<dd>${yi}<dd>`);

            defaultDl[1].innerHTML = '<dt>忌</dt>';
            data.yi.forEach(ji => defaultDl[1].innerHTML += `<dd>${ji}<dd>`);

            //hover对应的结构
            var str = '';
            var hoverDl = document.querySelectorAll('.suit .hover dl');
            data.yi.forEach(yi => str += `${yi}、`);
            hoverDl[0].innerHTML = '<dt>宜</dt><dd>' + str.substr(0, str.length - 1) + '</dd>';

            var str = '';
            data.ji.forEach(ji => str += `${ji}、`);
            hoverDl[1].innerHTML = '<dt>忌</dt><dd>' + str.substr(0, str.length - 1) + '</dd>';

        },

    };

    calendar.init();
})();